Skip to content

crypto/x509: Add VerifyOptions.UnknownAlgorithmVerifier #15

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

austinderek
Copy link

This allows callers to verify certificates using algorithms that Go does not support (yet).

For instance, here we're verifying the ML-KEM-512 example certificate from the LAMPS WG signed by a ML-DSA-44 public key.

package main

import (
        "crypto/x509"
        "crypto/x509/pkix"
        "encoding/asn1"
        "encoding/pem"
        "errors"
        "fmt"
        "github.com/cloudflare/circl/sign/schemes"
        "os"
)

func loadCert(path string) (*x509.Certificate, error) {
        raw, err := os.ReadFile(path)
        if err != nil {
                return nil, fmt.Errorf("ReadFile(%s): %w", path, err)
        }
        block, _ := pem.Decode(raw)
        if block == nil {
                return nil, fmt.Errorf("pem.Decode(%s) failed", path)
        }
        return x509.ParseCertificate(block.Bytes)
}

func main() {
        dsaCert, err := loadCert("ML-DSA-44.crt")
        if err != nil {
                panic(err)
        }
        kemCert, err := loadCert("ML-KEM-512.crt")
        if err != nil {
                panic(err)
        }

        roots := x509.NewCertPool()
        roots.AddCert(dsaCert)
        _, err = kemCert.Verify(x509.VerifyOptions{
                Roots: roots,
                UnknownAlgorithmVerifier: func(alg pkix.AlgorithmIdentifier,
                        signed, signature, pk []byte) error {
                        if !alg.Algorithm.Equal(asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 3, 17}) {
                                return errors.New("unsupported scheme")
                        }
                        scheme := schemes.ByName("ML-DSA-44")
                        ppk, err := scheme.UnmarshalBinaryPublicKey(pk)
                        if err != nil {
                                return err
                        }
                        if !scheme.Verify(ppk, signed, signature, nil) {
                                return errors.New("invalid signature")
                        }
                        return nil
                },
        })
        if err != nil {
                panic(err)
        }
}

🔄 This is a mirror of upstream PR #74023

This allows callers to verify certificates using algorithms that Go
does not support (yet).

For instance, here we're verifying the ML-KEM-512 example certificate
from the LAMPS WG signed by a ML-DSA-44 public key.

    https://github.com/lamps-wg/dilithium-certificates/blob/main/examples/ML-DSA-44.crt
    https://github.com/lamps-wg/kyber-certificates/blob/main/example/ML-KEM-512.crt

package main

import (
        "crypto/x509"
        "crypto/x509/pkix"
        "encoding/asn1"
        "encoding/pem"
        "errors"
        "fmt"
        "github.com/cloudflare/circl/sign/schemes"
        "os"
)

func loadCert(path string) (*x509.Certificate, error) {
        raw, err := os.ReadFile(path)
        if err != nil {
                return nil, fmt.Errorf("ReadFile(%s): %w", path, err)
        }
        block, _ := pem.Decode(raw)
        if block == nil {
                return nil, fmt.Errorf("pem.Decode(%s) failed", path)
        }
        return x509.ParseCertificate(block.Bytes)
}

func main() {
        dsaCert, err := loadCert("ML-DSA-44.crt")
        if err != nil {
                panic(err)
        }
        kemCert, err := loadCert("ML-KEM-512.crt")
        if err != nil {
                panic(err)
        }

        roots := x509.NewCertPool()
        roots.AddCert(dsaCert)
        _, err = kemCert.Verify(x509.VerifyOptions{
                Roots: roots,
                UnknownAlgorithmVerifier: func(alg pkix.AlgorithmIdentifier,
                        signed, signature, pk []byte) error {
                        if !alg.Algorithm.Equal(asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 3, 17}) {
                                return errors.New("unsupported scheme")
                        }
                        scheme := schemes.ByName("ML-DSA-44")
                        ppk, err := scheme.UnmarshalBinaryPublicKey(pk)
                        if err != nil {
                                return err
                        }
                        if !scheme.Verify(ppk, signed, signature, nil) {
                                return errors.New("invalid signature")
                        }
                        return nil
                },
        })
        if err != nil {
                panic(err)
        }
}
@austinderek austinderek force-pushed the master branch 29 times, most recently from 121e5bb to 7a1679d Compare August 5, 2025 07:04
@austinderek austinderek force-pushed the master branch 30 times, most recently from 5a56d88 to d50240b Compare August 19, 2025 07:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants